import 'package:flame/collisions.dart';
import 'package:flame/components.dart';
import 'package:flame/events.dart';
import 'package:flutter_flame/routes/RouteGame.dart';
import '../config/GameConfig.dart';
import '../worlds/game/GameWorld.dart';
import '../worlds/game/entity/SpriteAnimationParamEntity.dart';

// 实体类 - Sprite
abstract class SpriteAnimationEntity extends SpriteAnimationComponent
    with
        HasGameReference<RouterGame>,
        HasWorldReference<GameWorld>,
        CollisionCallbacks,
        TapCallbacks,
        GameConfig {
  double horizontalGap = 0; // 水平方向上的间距
  double verticalGap = 0; // 垂直方向上的间距
  SpriteAnimationParamEntity paramEntity;
  late RectangleHitbox rectangleHitBox;
  final Vector2? initPosition;

  SpriteAnimationEntity(this.paramEntity, {this.initPosition});

  @override
  Future<void> onLoad() async {
    await setSpriteAnimation(diffParam: paramEntity);
  }

  Vector2 get lawnSize => Vector2(
        cellSize.x * rows,
        cellSize.y * cols,
      );

  // 改变动画
  Future<void> setSpriteAnimation({
    SpriteAnimationParamEntity? diffParam,
    bool loop = true,
  }) async {
    final frames = <SpriteAnimationFrame>[];
    final tempParam = diffParam ?? paramEntity;
    double radio = 1.2;
    for (int i = 0; i < tempParam.frameNumber; i++) {
      final sprite = await Sprite.load('${tempParam.spritePath}$i.png');
      radio = sprite.image.width / sprite.image.height;
      frames.add(SpriteAnimationFrame(sprite, tempParam.stepTime));
    }
    animation = SpriteAnimation(frames, loop: loop);

    height = cellSize.y * tempParam.scaleSize;
    size = Vector2(height * radio, height);
    position = Vector2(
      (initPosition ?? position).x + (diffParam?.offsetX ?? 0),
      (initPosition ?? position).y + (diffParam?.offsetY ?? 0),
    );
  }

  // 添加碰撞矩阵
  void addHitBox({
    required double scaleHitBoxK,
    required Vector2 hitBoxPosition,
  }) {
    rectangleHitBox = RectangleHitbox(
      size: size * scaleHitBoxK,
      position: Vector2(
        (size * (1 - scaleHitBoxK)).x / 2 + hitBoxPosition.x,
        (size * (1 - scaleHitBoxK)).y / 2 + hitBoxPosition.y,
      ),
    );
    add(rectangleHitBox);
  }

  void removeHitBox() {
    remove(rectangleHitBox);
  }
}
